<template>
  <div class="chat-container" >
    <div class="chat-header">
      <div class="search-bar">
        <button class="icon-button">
          <img src="../assets/liandong.png" alt="logo" style="width: 40px; height: 40px;">
          <!-- <svg width="20" height="20" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
            <path d="M21 21L16.65 16.65M19 11C19 15.4183 15.4183 19 11 19C6.58172 19 3 15.4183 3 11C3 6.58172 6.58172 3 11 3C15.4183 3 19 6.58172 19 11Z" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
          </svg> -->
        </button>
        <span style="color: #2c2c36;
    font-size: 24px;
    font-weight: 600;">联东产业链大模型</span>
      </div>
      <div class="user-profile">
        <div class="profile-icon">联东</div>
      </div>
      <!-- 添加测试按钮 -->
      <!-- <el-button @click="testMindMap" type="primary" style="margin-right: 20px;">测试思维导图</el-button> -->
    </div>

    <div class="messages-container" ref="messagesContainer" :class="{ 'messages-container-with-input': messages.length === 0 }">
      <div class="welcome-message" v-if="showWelcomeMessage && isInitialLoad">
        <div class="welcome-content">
          <div class="welcome-header">
            <!-- <img src="../assets/robot-wave.gif" alt="AI Assistant" class="welcome-avatar"/> -->
            <h1>有什么可以帮忙的?</h1>
          </div>
          <div class="quick-actions">
                <div v-if="topConceptslist.length > 0" class="quick-action-row">
              <div class="quick-action-item" v-for="(concept, index) in topConceptslist.slice(0, 2)" :key="index" @click="quickAction(concept.concept_info)">
                <i class="el-icon-lightning"></i>
                <span>{{ concept.concept_info }}</span>
              </div>
            </div>
            <div v-if="topConceptslist.length > 2" class="quick-action-row">
              <div class="quick-action-item" v-for="(concept, index) in topConceptslist.slice(2, 4)" :key="index+2" @click="quickAction(concept.concept_info)">
                <i class="el-icon-cpu"></i>
                <span>{{ concept.concept_info }}</span>
              </div>
            </div>
            <!-- 当没有数据时的后备显示 -->
            <!-- <template v-if="topConceptslist.length === 0">
              <div class="quick-action-row">
                <div class="quick-action-item" @click="quickAction('深海探索')">
                  <i class="el-icon-lightning"></i>
                  <span>新能源产业分析</span>
                </div>
                <div class="quick-action-item" @click="quickAction('恐龙化石')">
                  <i class="el-icon-set-up"></i>
                  <span>半导体产业分析</span>
                </div>
              </div>
              <div class="quick-action-row">
                <div class="quick-action-item" @click="quickAction('斗破苍穹')">
                  <i class="el-icon-cpu"></i>
                  <span>机器人产业分析</span>
                </div>
                <div class="quick-action-item" @click="quickAction('斗罗大陆')">
                  <i class="el-icon-truck"></i>
                  <span>汽车产业分析</span>
                </div>
              </div>
            </template> -->
          </div>
          <div class="welcome-tips">
            <p>您也可以：</p>
            <ul>
              <li><i class="el-icon-search"></i> 搜索任意产业链信息</li>
              <li><i class="el-icon-data-analysis"></i> 查看产业链详细分析</li>
              <li><i class="el-icon-edit-outline"></i> 编辑和定制产业链图谱</li>
            </ul>
          </div>
        </div>
      </div>

      <div v-for="(message, index) in messages" :key="index" class="message" :class="message.role">
        <div class="message-content">
          <div class="message-avatar">
            <i v-if="message.role === 'user'" class="el-icon-user"></i>
            <img v-else src="../assets/liandong.png" alt="AI" style="width: 24px; height: 24px;">
          </div>
          <div class="message-text">
            <div v-if="message.role === 'assistant' && message.tasks && message.tasks.length > 0">
              <div v-for="(task, taskIndex) in message.tasks" :key="taskIndex" class="task-container" :class="{
                'collapsing': task.collapsing,
                'completed': task.completed
              }">
                <div class="task-header" @click="toggleTask(task)">
                  <h3 class="task-title" :class="{'task-title-bold': task.title.includes('任务')}">
                    {{ task.title }}
                    <i v-if="task.isCompleted" class="el-icon-check task-complete-icon"></i>
                  </h3>
                  <i :class="[task.collapsed ? 'el-icon-arrow-down' : 'el-icon-arrow-up', 'task-toggle-icon']"></i>
                </div>
                <ul class="task-steps" v-show="!task.collapsed">
                  <li v-for="(step, stepIndex) in task.steps" :key="stepIndex" class="task-step">
                    <div class="step-content">
                      <template v-if="step.type === 'mindmap'">
                        <div class="mindmap-container">
                          <MindView :data="step.data" />
                        </div>
                      </template>
                      <template v-else-if="step.isLink">
                        <a :href="step.url" target="_blank" class="article-link">{{ step.title }}</a>
                      </template>
                      <template v-else>
                        <typed-component
                          :text="step || ''"
                          :speed="typingSpeed"
                          @typing-complete="onTaskStepComplete(task, stepIndex)"
                        />
                      </template>
                      <span class="step-status">
                        <i v-if="stepIndex === task.steps.length - 1 && task.isTypingStep" class="el-icon-loading"></i>
                        <i v-else-if="task.showStepChecks && task.completedSteps[stepIndex]" class="el-icon-check"></i>
                      </span>
                    </div>
                  </li>
                  <!-- 只在当前活动任务中显示加载指示器 -->
                  <li v-if="(isProcessingMessage || pendingRequests.size > 0) && task.isActive && !task.isCompleted" class="task-step">
                    <div class="loading-indicator">
                      <div class="loading-dots">
                        <span></span>
                        <span></span>
                        <span></span>
                      </div>
                      <div class="loading-text">思考中...</div>
                    </div>
                  </li>
                </ul>
                <div v-if="task.title.includes('绘制') && task.steps.length >= 2 && task.steps[1].includes('已完成')" class="industry-chain-graph-container">
                  <industry-chain-graph :industryName="currentIndustryName"></industry-chain-graph>
                </div>
              </div>
            </div>
            <p v-else>
              <typed-component
                v-if="message.role === 'assistant'"
                :text="message.fullContent || ''"
                :speed="typingSpeed"
                @typing-complete="onTypingComplete(message)"
              />
              <span v-else>{{ message.content }}</span>
            </p>
          </div>
        </div>
      </div>

      <!-- 添加底部加载状态指示器 -->
      <!-- <div v-if="isProcessingMessage || pendingRequests.size > 0" class="loading-indicator">
        <div class="loading-dots">
          <span></span>
          <span></span>
          <span></span>
        </div>
        <div class="loading-text">正在思考...</div>
      </div> -->
    </div>

    <!-- 修改输入框容器的结构 -->
    <div class="input-wrapper">
      <div class="input-container"
           :class="{ 'input-container-bottom': messages.length > 0 }"
           @click="focusInput">
        <div class="input-box" @click="focusInput">
          <input
            type="text"
            v-model="inputMessage"
            placeholder="请输入您想了解的产业链信息..."
            @keydown.enter="sendMessage"
            ref="inputField"
            :disabled="isTyping"
          />
        </div>
        <div class="button-container">
          <div class="left-buttons">
            <el-popover
              placement="top"
              width="300"
              trigger="hover">
              <div class="file-list-popover">
                <div v-if="fileList.length === 0" class="no-files">
                  暂无已选择的文件
                </div>
                <div v-else class="file-list">
                  <div v-for="(file, index) in fileList" 
                       :key="index" 
                       class="file-item">
                    <div class="file-info">
                      <i class="el-icon-document"></i>
                      <span class="file-name">{{ file.name }}</span>
                    </div>
                    <div class="file-actions">
                      <el-button 
                        type="text" 
                        class="delete-btn"
                        @click="handleRemove(file, fileList)">
                        <i class="el-icon-delete"></i>
                      </el-button>
                    </div>
                  </div>
                </div>
              </div>
              <el-upload
                slot="reference"
                class="upload-demo"
                ref="upload"
                :action="uploadUrl"
                :headers="uploadHeaders"
                :data="{
                  folder: 'general'
                }"
                name="files"
                :auto-upload="false"
                :http-request="customUpload"
                :on-preview="handlePreview"
                :on-remove="handleRemove"
         
         
                :before-upload="beforeUpload"
                :file-list="fileList"
                :limit="5"
                :on-exceed="handleExceed"
                :on-change="handleFileChange"
                :show-file-list="false"
                multiple>
                <el-button size="small" type="primary" plain style="width: 130.09px;
      height: 100%;
      padding: 12px 20px;
      font-size: 14px;">
                  <i class="el-icon-paperclip"></i> 选择文件
                  <span v-if="fileList.length > 0" class="file-count">
                    ({{ fileList.length }})
                  </span>
                </el-button>
              </el-upload>
            </el-popover>
            <el-popover
              placement="bottom"
              trigger="hover"
              v-model="visible">
              <div>
                <div v-for="(site, index) in searchSites" :key="index" class="search-site">
                  <a :href="site.url" target="_blank">{{ site.name }}</a>
                  <div class="site-actions">
                    <el-button type="text" @click="editSite(index)" class="action-button">
                      <i class="el-icon-edit-outline"></i>
                      <span class="action-text">编辑</span>
                    </el-button>
                    <el-button type="text" @click="deleteSite(index)" class="action-button">
                      <i class="el-icon-delete"></i>
                      <span class="action-text">删除</span>
                    </el-button>
                  </div>
                </div>
                <el-button type="primary" size="small" @click="showAddEditDialog" style="width: 100%; margin-top: 10px;">
                  <i class="el-icon-plus"></i> 新增数据源
                </el-button>
              </div>
              <el-button slot="reference" @click="visible = !visible" type="primary" plain>
                <i class="el-icon-discover"></i> 搜索数据源
              </el-button>
            </el-popover>
          </div>
          <el-button type="primary" circle class="send-button" @click="sendMessage" :disabled="isTyping">
            <i class="el-icon-s-promotion"></i>
          </el-button>
        </div>
      </div>
    </div>



    <!-- 添加/编辑对话框 -->
    <el-dialog :title="dialogTitle" :visible.sync="addEditDialogVisible" width="30%">
      <el-form :model="siteForm" label-width="80px">
        <el-form-item label="网站名称">
          <el-input v-model="siteForm.name"></el-input>
        </el-form-item>
        <el-form-item label="网站URL">
          <el-input v-model="siteForm.url"></el-input>
        </el-form-item>
      </el-form>
      <span slot="footer" class="dialog-footer">
        <el-button @click="addEditDialogVisible = false">取 消</el-button>
        <el-button type="primary" @click="confirmAddEditSite">确 定</el-button>
      </span>
    </el-dialog>
  </div>
</template>

<script>
import IndustryChainGraph from './IndustryChainGraph.vue';
import TypedComponent from './TypedComponent.vue';
import MindView from './MindView.vue';
import { fetchEventSource } from '@microsoft/fetch-event-source'
import api from '@/api'
let task1 = {}
let relatedContent = {}
export default {
  name: 'ChatContainer',
  components: {
    IndustryChainGraph,
    TypedComponent,
    MindView
  },
  props: {
    mindViewData: {
      type: Object,
      default: null
    }
  },
  data() {
    return {
      inputMessage: '',
      visible: false,
      showWelcomeMessage: true,
      isInitialLoad: true,
      messages: [],
      messageQueue: [],
      isProcessingMessage: false,
      searchSites: [
        { name: '谷歌', url: 'google.com' },
        { name: '前瞻', url: 'qianzhan.com' },
        // { name: '知乎', url: 'zhihu.com' },
    
      ],
      siteForm: {
        name: '',
        url: ''
      },
      editingIndex: -1,
      selectedSite: 'https://www.google.com',
      addEditDialogVisible: false,
      isEditing: false,
      isTyping: false,
      typingSpeed: 0,
      fileList: [],
      currentIndustryName: '',
      currentCallback: null,
      processingMessage: false,
      currentType: null,
      messageBuffer: {},
      requestThrottleTime: 1000,
      lastRequestTime: 0,
      pendingRequests: new Set(),
      requestCache: new Map(),
      uploadHeaders: {
        Authorization: `${localStorage.getItem('token_type')} ${localStorage.getItem('access_token')}`
      },
      uploadedCount: 0,
      totalUploadCount: 0,
      uploadedFiles: [],
      lastMessageTime: Date.now(),
      loadingCheckInterval: null,
      processedMessageIds: new Set(),
      topConceptslist: [],
      _mindViewDebounceTimer: null,
      _lastMindViewDataFingerprint: null,
      currentQuery: null,
      currentTask: {},
      articleUrlSet: new Set(),
      accumulatedArticles: [],
      localRelatedContent: null,
      lastArticle: null,
      collectedArticles: [], // 添加新属性用于存储所有文章
    }
  },
  computed: {
    dialogTitle() {
      return this.isEditing ? '编辑搜索网站' : '添加搜索网站';
    },
    uploadUrl() {
      return `${process.env.VUE_APP_API_SERVER}/api/files/upload-multiple`;
    }
  },
  watch: {
    messages: {
      handler(newMessages) {
        if (newMessages.length > 0 && this.showWelcomeMessage) {
          this.showWelcomeMessage = false;
        }
      },
      deep: true
    },
    mindViewData: {
      handler(newData) {
        if (newData) {
          this.handleMindViewData(newData);
        }
      },
      immediate: true
    }
  },
  beforeRouteLeave(to, from, next) {
    // 路由切换时保存状态到sessionStorage
    sessionStorage.setItem('chat_state', JSON.stringify({
      messages: this.messages,
      showWelcomeMessage: this.showWelcomeMessage,
      pendingRequests: Array.from(this.pendingRequests)
    }));
    next();
  },
  mounted() {
    api.user.topconcepts().then(res=>{
      // console.log(res, '获取到的概念数据');
      if (res && res.data) {
        // 确保数据是数组形式
        this.topConceptslist = Array.isArray(res.data) ? res.data : 
                              (Array.isArray(res.data.data) ? res.data.data : []);
        // console.log(this.topConceptslist, '处理后的概念数据');
      }
    }).catch(err => {
      console.error('获取概念数据失败:', err);
      this.topConceptslist = [];
    })

    // 检查登录状态
    const accessToken = localStorage.getItem('access_token');
    const tokenType = localStorage.getItem('token_type');
    
    if (!accessToken || !tokenType) {
      localStorage.removeItem('isLoggedIn');
      this.$router.push('/login');
      return;
    }
    
    // 设置登录状态
    localStorage.setItem('isLoggedIn', 'true');
    this.isInitialLoad = true;
    
    // // 添加页面可见性变化监听
    // document.addEventListener('visibilitychange', () => {
      
    //   if (document.visibilityState === 'visible') {
    //     // 页面变为可见时,只恢复显示状态,不触发新请求
    //     const savedState = sessionStorage.getItem('chat_state');
    //     if (savedState) {
    //       const state = JSON.parse(savedState);
    //       // 只恢复显示状态
    //       this.showWelcomeMessage = state.showWelcomeMessage;
          
    //       // 如果有未完成的消息,则恢复消息
    //       if (state.messages && state.messages.length > 0) {
    //         const lastMessage = state.messages[state.messages.length - 1];
    //         // 只在最后一条消息未完成时才恢复
    //         if (lastMessage && !lastMessage.isCompleted) {
    //           this.messages = state.messages;
    //         }
    //       }
    //     }
    //   } else if (document.visibilityState === 'hidden') {
    //     // 页面隐藏时保存状态
    //     const stateToSave = {
    //       messages: this.messages,
    //       showWelcomeMessage: this.showWelcomeMessage
    //     };
    //     sessionStorage.setItem('chat_state', JSON.stringify(stateToSave));
    //   }
    // });
  },
  beforeDestroy() {
    // 移除事件监听器
    // document.removeEventListener('visibilitychange', this.handleVisibilityChange);
  },
  methods: {
    async processMessageQueue() {
      if (this.isProcessingMessage || this.messageQueue.length === 0) {
        return;
      }

      this.isProcessingMessage = true;
      const json = this.messageQueue.shift();

      try {
        await this.processMessage(json);
      } catch (error) {
        console.error('处理消息时出错:', error);
      } finally {
        this.isProcessingMessage = false;
        if (this.messageQueue.length > 0) {
          this.processMessageQueue();
        }
      }
    },

    async processMessage(json) {
      return new Promise(async (resolve) => {
        // 生成消息的唯一标识符
        const messageId = `${json.type}_${json.data}_${Date.now()}`;
        
        // 检查消息是否已经处理过
        if (this.processedMessageIds.has(messageId)) {
          // console.log('跳过重复消息:', messageId);
          resolve();
          return;
        }

        // 将消息ID添加到已处理集合中
        this.processedMessageIds.add(messageId);

        if (!relatedContent.articles) {
          relatedContent = {
            topic: {
              title: '产业链分析',
              type: 'industry',
              articleCount: 0,
              analysisCount: 0
            },
            articles: []
          };
        }

        if (this.messages.length < 2) {
          this.messages.push({
            role: 'assistant',
            content: '',
            isTyping: true,
            tasks: []
          });
        }

        // 检查是否是 ping 消息
        if (json.data && json.data.startsWith('ping')) {
          resolve();
          return;
        }

        // 处理消息结束信号
        if (json.data && (
          json.data.includes('处理结束') || 
          json.data.includes('分析结束') || 
          json.data.includes('总结完毕')
        )) {
          // 清理已处理消息ID集合
          this.processedMessageIds.clear();
          // console.log('处理完成，清理消息ID集合');
          
          if (this.loadingCheckInterval) {
            clearInterval(this.loadingCheckInterval);
            this.loadingCheckInterval = null;
          }
          this.pendingRequests.delete(this.currentQuery);
          resolve();
          return;
        }

        if (json.type === '1') {
          // 处理上一个任务的完成状态
          if (task1.steps && task1.steps.length > 0) {
            // 等待当前任务的所有打字效果完成
            if (task1.isTypingStep) {
              await new Promise(resolveWait => {
                const checkTyping = setInterval(() => {
                  if (!task1.isTypingStep) {
                    clearInterval(checkTyping);
                    // 设置完成状态
                    task1.showStepChecks = true;
                    task1.completed = true;
                    task1.isCompleted = true;
                    task1.isActive = false;
                    if (!task1.userCollapsed) {
                      task1.collapsed = true;
                    }
                    resolveWait();
                  }
                }, 100);
              });
            } else {
              // 直接设置完成状态
              task1.showStepChecks = true;
              task1.completed = true;
              task1.isCompleted = true;
              task1.isActive = false;
              if (!task1.userCollapsed) {
                task1.collapsed = true;
              }
            }
          }

          // 将所有现有任务设置为非活动状态
          if (this.messages[1] && this.messages[1].tasks) {
            this.messages[1].tasks.forEach(t => {
              t.isActive = false;
            });
          }

          // 创建新任务
          task1 = {
            title: json.data,
            steps: [],
            collapsed: false,
            currentStep: 0,
            stepContent: '',
            isTypingStep: false,
            totalSteps: 2,
            isCompleted: false,
            completed: false,
            isActive: true,
            completedSteps: {},
            showStepChecks: false,
            userCollapsed: false
          };

          if (!this.messages[1].tasks) {
            this.$set(this.messages[1], 'tasks', []);
          }

          this.messages[1].tasks.push(task1);
          this.scrollToBottom();
          resolve();
        } else if (json.type === '2') {
          if (task1 && json.data) {
            let formattedData = json.data;
            if (json.data.includes('产业链信息') || json.data.includes('产业链总结')) {
              formattedData = `\n${json.data}`;
            }
            if (json.data.startsWith('ping')) {
              resolve();
              return;
            }

            // 在每次收到 type 2 消息时,如果有收集的文章,则更新侧边栏
            if (this.collectedArticles.length > 0) {
              const relatedContent = {
                topic: {
                  title: this.currentQuery || '产业链分析',
                  type: 'industry',
                  articleCount: this.collectedArticles.length,
                  analysisCount: 0
                },
                articles: [...this.collectedArticles] // 使用展开运算符创建新数组
              };
              
              // 更新侧边栏
              this.$root.$emit('update-sidebar', relatedContent);
              
              // 清空收集的文章,为下一次 type 2 消息做准备
              this.collectedArticles = [];
            }

            // 等待上一个打字效果完成
            if (task1.isTypingStep) {
              await new Promise(resolveWait => {
                const checkTyping = setInterval(() => {
                  if (!task1.isTypingStep) {
                    clearInterval(checkTyping);
                    resolveWait();
                  }
                }, 100);
              });
            }

            await new Promise(resolveTyping => {
              this.typeTaskStep(task1, formattedData, resolveTyping);
            });
          }
          resolve();
        } else if (json.type === '3') {
          try {
            let relations = [];
            let nodes = [];
            if (typeof json.data === 'string') {
              // 处理返回的数据格式
              const lines = json.data.split('\n');
              lines.forEach(line => {
                if (line.includes('relations:')) {
                  try {
                    // 提取 relations 后面的数组字符串
                    const relationsStr = line.split('relations:')[1].trim();
                    // 解析数组字符串
                    relations = JSON.parse(relationsStr);
                    // console.log('解析到的relations数据:', relations);
                  } catch (e) {
                    console.error('解析relations数据失败:', e);
                  }
                }
         
              });
            }
            if (typeof json.data === 'string') {
              // 处理返回的数据格式
              const lines = json.data.split('\n');
              lines.forEach(line => {
                if (line.includes('nodes:')) {
                  try {
                    // 提取 nodes 后面的数组字符串
                    const relationsStr = line.split('nodes:')[1].trim();
                    // 解析数组字符串
                    nodes = JSON.parse(relationsStr);
                    // console.log('解析到的relations数据:', nodes);
                  } catch (e) {
                    console.error('解析relations数据失败:', e);
                  }
                }
         
              });
            }

            // 确保有数据再创建思维导图 (至少有relations数据)
            if (relations && relations.length > 0) {
              // console.log('准备创建思维导图，relations数据:', relations);
              // console.log('nodes数据:', nodes);
              
              // 数据指纹，用于去重，同时包含nodes和relations
              const dataFingerprint = JSON.stringify({relations, nodes});
              
              // 检查是否已经显示了完全相同的数据
              if (this._lastMindViewDataFingerprint === dataFingerprint) {
                // console.log('[processMessage] 跳过重复的思维导图数据');
                resolve();
                return;
              }
              
              // 保存数据指纹用于去重
              this._lastMindViewDataFingerprint = dataFingerprint;
              
              // 创建思维导图任务，添加随机后缀确保唯一性
              const randomSuffix = Math.floor(Math.random() * 1000);
              const mindmapTask = {
                title: `消息产业链关系图 #${randomSuffix}`,
                steps: [{
                  type: 'mindmap',
                  data: { 
                    relations: relations,
                    nodes: nodes,
                
                    industry_name: this.currentQuery || ''
                  }
                }],
                collapsed: false,
                isTypingStep: false,
                isCompleted: true,
                completed: true,
                isActive: true,
                completedSteps: {},
                showStepChecks: true
              };

              // 确保消息列表存在
              if (!this.messages[1]) {
                this.messages.push({
                  role: 'assistant',
                  content: '',
                  isTyping: false,
                  tasks: []
                });
              }

              if (!this.messages[1].tasks) {
                this.$set(this.messages[1], 'tasks', []);
              }
              
              // 直接添加新的思维导图任务
              this.messages[1].tasks.push(mindmapTask);

              // 确保视图更新并滚动到底部
              this.$nextTick(() => {
                // console.log('思维导图任务已添加:', mindmapTask);
                this.scrollToBottom();
                resolve();
              });
            } else {
              // 没有 relations 或 nodes 数据时,将消息内容添加到当前任务的步骤中
              if (task1 && json.data) {
                // 等待上一个打字效果完成
                if (task1.isTypingStep) {
                  await new Promise(resolveWait => {
                    const checkTyping = setInterval(() => {
                      if (!task1.isTypingStep) {
                        clearInterval(checkTyping);
                        resolveWait();
                      }
                    }, 100);
                  });
                }

                await new Promise(resolveTyping => {
                  this.typeTaskStep(task1, json.data, resolveTyping);
                });
              }
              resolve();
            }
          } catch (error) {
            // JSON 解析失败,说明是普通文本,直接添加到任务步骤中
            if (task1 && json.data) {
              // 等待上一个打字效果完成
              if (task1.isTypingStep) {
                await new Promise(resolveWait => {
                  const checkTyping = setInterval(() => {
                    if (!task1.isTypingStep) {
                      clearInterval(checkTyping);
                      resolveWait();
                    }
                  }, 100);
                });
              }

              await new Promise(resolveTyping => {
                this.typeTaskStep(task1, json.data, resolveTyping);
              });
            }
            resolve();
          }
        } else if (json.type === '5') {
          const urlMatch = json.data.match(/(.+?)url:(.+)/i);
          if (urlMatch) {
            const title = urlMatch[1].trim();
            const url = urlMatch[2].trim();
            
            // 将文章添加到收集数组中
            this.collectedArticles.push({
              title: title,
              url: url,
              summary: '',
              source: '行业报告',
              date: new Date().toLocaleDateString(),
              type: 'industry'
            });

            if (task1 && task1.steps) {
              task1.steps.push({
                isLink: true,
                title: title,
                url: url
              });
              
              this.$nextTick(() => {
                this.scrollToBottom();
                resolve();
              });
            } else {
              resolve();
            }
          } else {
            resolve();
          }
        } else {
          resolve();
        }
      });
    },
    createSSE(v) {
     
      this.isInitialLoad = false;
      // 如果页面不可见,不发送请求
      // if (document.visibilityState !== 'visible') {
      //   return;
      // }

      // // 检查是否有相同请求正在处理中
      // if (this.pendingRequests.has(v)) {
      //   this.$message.warning('已有相同请求正在处理中，请等待完成');
      //   return;
      // }

      // 添加到待处理请求集合中
      this.pendingRequests.add(v);
      
      // 保存当前查询内容
      this.currentQuery = v;
      
      // 每次新请求时重置文章收集状态
      this.articleUrlSet = new Set();
      this.accumulatedArticles = [];
      
      // 重置本地相关内容对象，为新请求做准备
      this.localRelatedContent = {
        topic: {
          title: v || '产业链分析',
          type: 'industry',
          articleCount: 0,
          analysisCount: 0
        },
        articles: []
      };

      const that = this;
      const controller = new AbortController();
      const signal = controller.signal;
      const url = `${process.env.VUE_APP_API_SERVER}/api/industrial/process_stream`;
      const accessToken = localStorage.getItem('access_token');
      const tokenType = localStorage.getItem('token_type');

      if (!accessToken || !tokenType) {
        console.error('Token不存在，请先登录');
        // 清除登录状态
        localStorage.removeItem('isLoggedIn');
        localStorage.removeItem('access_token');
        localStorage.removeItem('token_type');
        this.pendingRequests.delete(v);
        
        // 先显示消息提示
        this.$message({
          message: '请先登录',
          type: 'error',
          duration: 2000,
          onClose: () => {
            // 消息关闭后再跳转
            this.$router.push('/login');
          }
        });
        return;
      }

      let isConnectionClosed = false;
      let hasError = false;

      const startFetchEventSource = () => {
        if (isConnectionClosed || hasError) {
          return;
        }

        fetchEventSource(url, {
          method: 'POST',
          signal: signal,
          headers: {
            'Authorization': `${tokenType} ${accessToken}`,
            'Content-Type': 'application/json'
          },
          body: JSON.stringify({
            industry_name: v,
            custom_urls: this.fileList.map(file => file.response?.fileurl).filter(Boolean),
            sites: this.searchSites.map(site => site.url) // 只传递域名部分
          }),
          openWhenHidden: true,
          onopen(response) {
            if (response.ok && response.status === 200) {
              // console.log('Connection opened for query:', v);
              console.log('------- concent --------- ');
            } else if (response.status === 401) {
              console.error('Token已失效，请重新登录');
              that.$message.error('登录已过期，请重新登录');
              localStorage.removeItem('access_token');
              localStorage.removeItem('token_type');
              that.$router.push('/login');


            } else {
              console.error(`连接状态异常: ${response.status}`);
            }
          },
          onmessage(msg) {
            
            // console.log('msg', msg);
            if (!msg || !msg.data) return;
            
            // 更新最后收到消息的时间
            that.lastMessageTime = Date.now();
            
            let json = {};
            const messageData = msg.data;
            // console.log('messageData', messageData);
            try {
              const lines = messageData.split('\n').filter(line => line.trim());
              lines.forEach(line => {
                line = line.trim();
                if (line.includes('type:')) {
                  json.type = line.split('type:')[1].trim();
                } else if (line.startsWith('data:')) {
                  let content = line.substring(5).trim();
                  if (content.startsWith('data:')) {
                    content = content.substring(5).trim();
                  }
                  json.data = (json.data ? json.data + '\n' : '') + content;
                } else if (line.trim().length > 0) {
                  json.data = (json.data ? json.data + '\n' : '') + line;
                }
              });

              if (json.data) {
                // 检查是否是ping消息
                if (json.data.startsWith('ping')) {
                  // 更新当前消息的内容为加载状态
                  const currentMessage = that.messages[that.messages.length - 1];
                  if (currentMessage && currentMessage.role === 'assistant') {
                    currentMessage.content = '正在思考...';
                    that.$nextTick(() => {
                      that.scrollToBottom();
                    });
                  }
                  return;
                }

                json.data = json.data
                  .replace(/#{1,6}\s+/g, '')
                  .replace(/\*\*(.*?)\*\*/g, '$1')
                  .replace(/###|####/g, '')
                  .replace(/^\s*[-—]\s*/g, '')
                  .replace(/^\s*\d+\.\s*/g, '')
                  .replace(/^data[:：]\s*/g, '')
                  .trim();
              }

              // 检查是否是处理结束的信号
              if (json.data && (
                json.data.includes('处理结束') || 
                json.data.includes('分析结束') || 
                json.data.includes('总结完毕')
              )) {
                // console.log('处理完成，准备更新侧边栏');
                
                // 清理定时器
                if (that.loadingCheckInterval) {
                  clearInterval(that.loadingCheckInterval);
                  that.loadingCheckInterval = null;
                }
                
                // 请求结束时，一次性更新侧边栏
                that.updateSidebarWithAccumulatedArticles();
                
                that.pendingRequests.delete(v);
                return;
              }

              if (Object.keys(json).length > 0) {
                that.messageQueue.push(json);
                if (!that.isProcessingMessage) {
                  that.processMessageQueue();
                }
              }
            } catch (error) {
              console.error('处理消息时出错:', error);
              // 只记录错误，不中断连接
            }
          },
          onerror(err) {
            console.error('EventSource error:', err);
            // 只记录错误，不中断连接
          },
          onclose() {
            // console.log('Connection closed by the server');
            // 清理定时器
            if (that.loadingCheckInterval) {
              clearInterval(that.loadingCheckInterval);
              that.loadingCheckInterval = null;
            }
            
            // 确保在连接关闭时更新侧边栏
            that.updateSidebarWithAccumulatedArticles();
            
            that.pendingRequests.delete(v);
          }
        });
      };

      startFetchEventSource();

      // 简化清理逻辑
      controller.signal.addEventListener('abort', () => {
        this.pendingRequests.delete(v);
      });
    },
    sendMessage(event) {
      this.isInitialLoad = false;
      if (this.isTyping) {
        return;
      }
      
      if (event && event.type === 'keydown' && !event.shiftKey && event.key === 'Enter') {
        event.preventDefault();
      }
      
      let query = this.inputMessage || this.query;
      if (!query || query.trim() === '') {
        return;
      }
      
      // 检查是否有请求正在处理中
      if (this.isProcessingMessage || this.pendingRequests.size > 0) {
        this.$message.warning('请等待当前请求处理完成');
        return;
      }
      
      const userMessage = query.trim();
      // 设置当前查询，在整个请求生命周期内使用
      this.currentQuery = userMessage;
      
      // 清空以前的文章URL集合和累积的文章 - 关键修改：每次新查询时完全重置
      this.articleUrlSet = new Set(); // 完全重新创建集合，而不是仅清空
      this.accumulatedArticles = []; // 重置累积的文章
      
      // 初始化本地相关内容
      this.localRelatedContent = {
        topic: {
          title: userMessage,
          type: 'industry',
          articleCount: 0,
          analysisCount: 0
        },
        articles: []
      };
      
      // 添加用户消息
      this.messages.push({
        role: 'user',
        content: userMessage,
        tasks: []
      });

      this.inputMessage = '';
      this.showWelcomeMessage = false;

      // 添加助手消息
      this.messages.push({
        role: 'assistant',
        content: '',
        isTyping: true,
        tasks: []
      });
      
      // 如果有待处理的相同查询，返回
      if (this.pendingRequests.has(userMessage)) {
        // console.log('[sendMessage] 已有相同的查询正在处理中', userMessage);
        return;
      }
      
      this.pendingRequests.add(userMessage);
      
      // 滚动到底部
      this.$nextTick(() => {
        this.scrollToBottom();
        this.createSSE(userMessage);
      });
    },

    extractIndustryName(message) {
      const matches = message.match(/[「『"']([^「『"']+)[」』"']产业/);
      if (matches && matches[1]) {
        return matches[1];
      }

      const words = message.split(/\s+/);
      for (const word of words) {
        if (word.length >= 2 && !word.includes('产业链') && !word.includes('分析')) {
          return word;
        }
      }

      return '新能源';
    },

    typeTaskStep(task, content, callback) {
      if (!task) return;
      
      if (!task.completedSteps) {
        this.$set(task, 'completedSteps', {});
      }
      if (!task.showStepChecks) {
        task.showStepChecks = false;
      }
      const stepIndex = task.steps ? task.steps.length : 0;

      if (!task.steps) {
        this.$set(task, 'steps', []);
      }

      const urlMatch = content.match(/(.+?)url:(.+)/i);
      if (urlMatch) {
        task.steps.push({
          isLink: true,
          title: urlMatch[1].trim(),
          url: urlMatch[2].trim()
        });
        if (callback) {
          this.$nextTick(() => {
            callback();
          });
        }
      } else {
        task.steps.push(content);
        task.isTypingStep = true;
        task.isActive = true;

        if (stepIndex === 0) {
          task.isCompleted = false;
          task.completed = false;
          task.collapsed = false;
        }

        this.scrollToBottom();

        // 减少延迟时间，使用固定的较短延迟
        if (callback) {
          setTimeout(() => {
            callback();
          }, Math.min(content.length * 10, 500)); // 最多等待500ms
        }
      }
    },

    onTaskStepComplete(task, stepIndex) {
      if (!task || !task.steps) return;
      
      if (stepIndex === task.steps.length - 1) {
        task.isTypingStep = false;
      }

      if (!task.completedSteps) {
        this.$set(task, 'completedSteps', {});
      }

      // 设置当前步骤为已完成
      this.$set(task.completedSteps, stepIndex, true);
      
      // 显示步骤的对勾图标
      task.showStepChecks = true;

      this.$nextTick(() => {
        this.processNextStep(task);
      });
    },

    processNextStep(task) {
      if (!task || !task.steps) return;
      
      const currentStepIndex = Object.keys(task.completedSteps).length;
      if (currentStepIndex < task.steps.length) {
        this.$nextTick(() => {
          this.scrollToBottom();
        });
      } else {
        this.$nextTick(() => {
          this.scrollToBottom();
        });
      }
    },

    startTypingEffect(messageIndex) {
      this.isTyping = true;
      const message = this.messages[messageIndex];
      const fullContent = message.fullContent;
      let currentIndex = 0;

      const typingInterval = setInterval(() => {
        if (currentIndex < fullContent.length) {
          this.messages[messageIndex].content = fullContent.substring(0, currentIndex + 1);
          currentIndex++;

          this.scrollToBottom();
        } else {
          clearInterval(typingInterval);
          this.messages[messageIndex].isTyping = false;
          this.isTyping = false;
        }
      }, this.typingSpeed);
    },

    scrollToBottom() {
      this.$nextTick(() => {
        const container = this.$refs.messagesContainer;
        if (container) {
          const scrollOptions = {
            top: container.scrollHeight,
            behavior: 'smooth'
          };

          const isLargeScroll = container.scrollHeight - container.scrollTop > container.clientHeight * 2;
          if (isLargeScroll) {
            scrollOptions.behavior = 'auto';
          }

          container.scrollTo(scrollOptions);
        }
      });
    },


    showAddEditDialog() {
      this.isEditing = false;
      this.siteForm.name = '';
      this.siteForm.url = '';
      this.addEditDialogVisible = true;
    },

    editSite(index) {
      this.isEditing = true;
      this.editingIndex = index;
      this.siteForm.name = this.searchSites[index].name;
      this.siteForm.url = this.searchSites[index].url;
      this.addEditDialogVisible = true;
    },

    confirmAddEditSite() {
      if (this.isEditing) {
        if (this.editingIndex !== -1) {
          // 确保只保存域名部分，移除可能的协议和路径
          const url = this.siteForm.url.replace(/^(https?:\/\/)?(www\.)?/i, '').split('/')[0];
          this.searchSites[this.editingIndex].name = this.siteForm.name;
          this.searchSites[this.editingIndex].url = url;
          this.editingIndex = -1;
        }
      } else {
        if (this.siteForm.name && this.siteForm.url) {
          // 确保只保存域名部分，移除可能的协议和路径
          const url = this.siteForm.url.replace(/^(https?:\/\/)?(www\.)?/i, '').split('/')[0];
          this.searchSites.push({ name: this.siteForm.name, url: url });
        }
      }
      this.addEditDialogVisible = false;
      
      // 确保数据状态更新后，如果有活动查询，则更新请求
      if (this.currentQuery && !this.pendingRequests.has(this.currentQuery)) {
        this.$nextTick(() => {
          this.createSSE(this.currentQuery);
        });
      }
    },

    deleteSite(index) {
      this.searchSites.splice(index, 1);
      
      // 确保数据状态更新后，如果有活动查询，则更新请求
      if (this.currentQuery && !this.pendingRequests.has(this.currentQuery)) {
        this.$nextTick(() => {
          this.createSSE(this.currentQuery);
        });
      }
    },
    handleClickOutside(event) {
      const inputBox = this.$refs.inputBox;
      const inputField = this.$refs.inputField;
      if (inputBox && !inputBox.contains(event.target)) {
        inputField.focus();
      }
    },
    handlePreview() {
      // 文件预览方法
    },
    handleRemove(file, fileList) {
      this.fileList = fileList;
    },
    handleExceed(files, fileList) {
      this.$message.warning(`当前限制选择 5 个文件，本次选择了 ${files.length} 个文件，共选择了 ${files.length + fileList.length} 个文件`);
    },
    toggleTask(task) {
      if (task.isCompleted || task.isActive) {
        task.collapsed = !task.collapsed;
        task.userCollapsed = !task.collapsed;
      }
    },
    onTypingComplete(message) {
      message.isTyping = false;
      this.isTyping = false;
    },
    quickAction(action) {
      this.isInitialLoad = false;
      // 检查是否有请求正在处理中
      if (this.isProcessingMessage || this.pendingRequests.size > 0) {
        this.$message.warning('请等待当前请求处理完成');
        return;
      }

      this.inputMessage = action;
      this.messages.push({
        role: 'user',
        content: action,
        tasks: []
      });

      this.showWelcomeMessage = false;

      this.messages.push({
        role: 'assistant',
        content: '',
        isTyping: true,
        tasks: []
      });

      this.$nextTick(() => {
        this.scrollToBottom();
        this.createSSE(action);
      });
    },
    async handleAIResponse(message) {
      const relatedContent = await this.generateRelatedContent(message)

      this.$root.$emit('update-sidebar', relatedContent)
    },
    async generateRelatedContent(message) {
      const topic = {
        title: '机器人产业链分析',
        type: 'industry',
        articleCount: 12,
        analysisCount: 3
      }

      const articles = [
        {
          type: '深度分析',
          date: '2024-03-15',
          title: '2024年机器人行业市场规模及发展前景分析',
          summary: '随着人工智能技术的快速发展，机器人产业迎来新的发展机遇...',
          source: '前瞻产业研究院',
          url: 'https://example.com/article1'
        }
      ]

      const marketData = [
        {
          title: '市场规模',
          value: '2,358亿元',
          changeRate: '+15.6%',
          trend: 'up',
          icon: 'el-icon-money'
        }
      ]

      const companies = [
        {
          name: '科大讯飞',
          type: '人工智能',
          logo: 'https://example.com/logo1.png',
          stockCode: 'SZ002230',
          price: '48.25',
          priceChange: 2.35
        }
      ]

      return {
        topic,
        articles,
        marketData,
        companies
      }
    },
    focusInput() {
      this.$refs.inputField.focus();
    },
    beforeUpload(file) {
      // 文件类型限制
      const allowedTypes = ['image/jpeg', 'image/png', 'application/pdf', 'application/msword', 
                        'application/vnd.openxmlformats-officedocument.wordprocessingml.document'];
      const isValidType = allowedTypes.includes(file.type);
      
      // 文件大小限制（10MB）
      const isLt10M = file.size / 1024 / 1024 < 10;

      if (!isValidType) {
        this.$message.error('只能上传 JPG/PNG/PDF/DOC/DOCX 格式的文件!');
        return false;
      }
      
      if (!isLt10M) {
        this.$message.error('文件大小不能超过 10MB!');
        return false;
      }
      
      return true;
    },
    
    handleFileChange(file, fileList) {
      // 当文件状态改变时（添加/删除），这个方法会被调用
      if (fileList.length > 0) {
        // 检查是否所有文件都符合要求
        const invalidFiles = fileList.filter(f => !this.validateFile(f.raw));
        if (invalidFiles.length > 0) {
          this.$message.error('存在不符合要求的文件，请检查后重试');
          // 从文件列表中移除不符合要求的文件
          invalidFiles.forEach(invalidFile => {
            const index = fileList.indexOf(invalidFile);
            if (index > -1) {
              fileList.splice(index, 1);
            }
          });
          return;
        }

        // 创建 FormData
        const formData = new FormData();
        fileList.forEach(f => {
          formData.append('files', f.raw);
        });
        formData.append('folder', 'general');

        // 发起上传请求
        fetch(this.uploadUrl, {
          method: 'POST',
          headers: {
            Authorization: this.uploadHeaders.Authorization
          },
          body: formData
        })
        .then(response => {
          if (!response.ok) {
            throw new Error('上传失败');
          }
          return response.json();
        })
        .then(result => {
          if (result.files && result.files.length > 0) {
            result.files.forEach(fileInfo => {
              const targetFile = fileList.find(f => f.name === fileInfo.file_name);
              if (targetFile) {
                targetFile.response = {
                  fileurl: fileInfo.file_url
                };
              }
            });
            this.fileList = [...fileList]; // 使用展开运算符创建新数组
            this.$message.success('所有文件上传成功');
          }
        })
        .catch(error => {
          console.error('上传错误:', error);
          this.$message.error('文件上传失败');
          // 发生错误时清空文件列表
          this.fileList = [];
        });
      }
    },
    
    validateFile(file) {
      // 文件类型限制
      const allowedTypes = ['image/jpeg', 'image/png', 'application/pdf', 'application/msword', 
                        'application/vnd.openxmlformats-officedocument.wordprocessingml.document'];
      const isValidType = allowedTypes.includes(file.type);
      
      // 文件大小限制（10MB）
      const isLt10M = file.size / 1024 / 1024 < 10;
      
      return isValidType && isLt10M;
    },
    async customUpload({ file }) {
      // 这里不需要做任何事情，因为我们会在submitUpload中统一处理
      return false;
    },
    // 新增方法：直接接收思维导图数据并显示
    receiveMindViewData(data) {
      if (!data) return;
      
      // 添加防抖处理，防止短时间内多次调用
      if (this._mindViewDebounceTimer) {
        clearTimeout(this._mindViewDebounceTimer);
      }
      
      this._mindViewDebounceTimer = setTimeout(() => {
        // 数据指纹，用于去重
        const dataFingerprint = JSON.stringify(data);
        
        // 检查是否已经显示了完全相同的数据
        if (this._lastMindViewDataFingerprint === dataFingerprint) {
          // console.log('[ChatContainer] 跳过重复的思维导图数据');
          return;
        }
        
        // 保存数据指纹用于去重
        this._lastMindViewDataFingerprint = dataFingerprint;
        
        // console.log('[ChatContainer] 显示思维导图数据');
        
        // 确保数据包含relations，如果没有则创建空数组
        if (!data.relations) {
          data.relations = [];
        }
        
        // 确保数据包含nodes，如果没有则创建空数组
        if (!data.nodes) {
          data.nodes = [];
        }
        
        // 确保有行业名称
        if (!data.industry_name) {
          data.industry_name = '';
        }
        
        // 创建一个新的思维导图任务
        const randomSuffix = Math.floor(Math.random() * 1000);
        const mindmapTask = {
          title: `Sidebar产业链关系图 #${randomSuffix}`,
          steps: [{
            type: 'mindmap',
            data: data
          }],
          collapsed: false,
          isTypingStep: false,
          isCompleted: true,
          completed: true,
          isActive: true,
          completedSteps: {},
          showStepChecks: true
        };

        // 确保有一个消息来容纳任务
        if (!this.messages.length) {
          this.messages.push({
            role: 'assistant',
            content: '',
            isTyping: false,
            tasks: []
          });
        }

        // 确保第一条消息有tasks数组
        if (!this.messages[0].tasks) {
          this.$set(this.messages[0], 'tasks', []);
        }

        // 直接添加新任务到第一条消息的任务列表中
        this.messages[0].tasks.push(mindmapTask);
        this.showWelcomeMessage = false;

        // 滚动到底部确保新的思维导图可见
        this.$nextTick(() => {
          this.scrollToBottom();
        });
      }, 300); // 300ms的防抖时间
    },
    // 处理思维导图数据并显示，为了兼容性保留此方法
    handleMindViewData(data) {
      // 直接调用新的方法
      this.receiveMindViewData(data);
    },
    // 添加测试方法
    testMindMap() {
      // 测试数据
      const testRelations = [
      "上游-2,OpenAI-1,part-of",
    "中游-3,OpenAI-1,part-of",
    "下游-4,OpenAI-1,part-of",
    "算力基础设施-5,上游-2,part-of",
    "GPU芯片-6,算力基础设施-5,part-of",
    "云计算平台-7,算力基础设施-5,part-of",
    "专用计算芯片-8,算力基础设施-5,part-of",
    "数据资源-9,上游-2,part-of",
    "训练数据集-10,数据资源-9,part-of",
    "数据标注服务-11,数据资源-9,part-of",
    "基础软件-12,上游-2,part-of",
    "深度学习框架-13,基础软件-12,part-of",
    "分布式训练系统-14,基础软件-12,part-of",
    "数据处理工具链-15,基础软件-12,part-of",
    "大模型研发-16,中游-3,part-of",
    "模型架构设计-17,大模型研发-16,part-of",
    "预训练模型开发-18,大模型研发-16,part-of",
    "模型优化技术-19,大模型研发-16,part-of",
    "训练平台-20,中游-3,part-of",
    "应用接口层-21,下游-4,part-of",
    "API服务-22,应用接口层-21,part-of",
    "模型即服务平台-23,应用接口层-21,part-of",
    "垂直领域应用-24,下游-4,part-of",
    "代码生成-25,垂直领域应用-24,part-of",
    "图像生成-26,垂直领域应用-24,part-of",
    "智能对话系统-27,垂直领域应用-24,part-of",
    "文档处理-28,垂直领域应用-24,part-of",
    "部署支持-29,下游-4,part-of",
    "模型部署工具链-30,部署支持-29,part-of",
    "边缘计算适配-31,部署支持-29,part-of",
    "多模态集成方案-32,部署支持-29,part-of"
      ]
      // 添加测试nodes数据
      const testNodes = [
      "OpenAI", 
    "上游", 
    "中游", 
    "下游", 
    "算力基础设施", 
    "GPU芯片", 
    "云计算平台", 
    "专用计算芯片", 
    "数据资源", 
    "训练数据集", 
    "数据标注服务", 
    "基础软件", 
    "深度学习框架", 
    "分布式训练系统", 
    "数据处理工具链", 
    "大模型研发", 
    "模型架构设计", 
    "预训练模型开发", 
    "模型优化技术", 
    "训练平台", 
    "应用接口层", 
    "API服务", 
    "模型即服务平台", 
    "垂直领域应用", 
    "代码生成", 
    "图像生成", 
    "智能对话系统", 
    "文档处理", 
    "部署支持", 
    "模型部署工具链", 
    "边缘计算适配", 
    "多模态集成方案"
     
       
      ]
      // 创建一个思维导图数据对象
      const mindmapData = {
        relations: testRelations,
        nodes: testNodes,
        industry_name: 'OpenAI'
      };
      
      // 创建一个新的思维导图任务
      const randomSuffix = Math.floor(Math.random() * 1000);
      const mindmapTask = {
        title: `测试产业链关系图 #${randomSuffix}`,
        steps: [{
          type: 'mindmap',
          data: mindmapData
        }],
        collapsed: false,
        isTypingStep: false,
        isCompleted: true,
        completed: true,
        isActive: true,
        completedSteps: {},
        showStepChecks: true
      };

      // 确保有一个消息来容纳任务
      if (!this.messages.length) {
        this.messages.push({
          role: 'assistant',
          content: '',
          isTyping: false,
          tasks: []
        });
      }

      // 确保第一条消息有tasks数组
      if (!this.messages[0].tasks) {
        this.$set(this.messages[0], 'tasks', []);
      }

      // 直接添加新任务到第一条消息的任务列表中
      this.messages[0].tasks.push(mindmapTask);
      this.showWelcomeMessage = false;

      // 滚动到底部确保新的思维导图可见
      this.$nextTick(() => {
        this.scrollToBottom();
      });
    },
    // 更新侧边栏，一次性处理所有累积的文章
    updateSidebarWithAccumulatedArticles() {
      // console.log('开始更新侧边栏，累积文章数量:', this.accumulatedArticles ? this.accumulatedArticles.length : 0);
      
      // 确保数组存在
      if (!this.accumulatedArticles) {
        this.accumulatedArticles = [];
      }
      
      // 如果没有累积的文章，不需要更新
      if (this.accumulatedArticles.length === 0) {
        // console.log('没有累积的文章，跳过侧边栏更新');
        return;
      }
      
      // 使用严格去重逻辑处理文章列表
      const uniqueArticles = this.removeDuplicates(this.accumulatedArticles);
      // console.log(`文章去重: ${this.accumulatedArticles.length} -> ${uniqueArticles.length}`);
      
      // 确保本地相关内容对象存在
      if (!this.localRelatedContent) {
        this.localRelatedContent = {
          topic: {
            title: this.currentQuery || '产业链分析',
            type: 'industry',
            articleCount: 0,
            analysisCount: 0
          },
          articles: []
        };
      }
      
      // 设置新的本地相关内容
      this.localRelatedContent = {
        topic: {
          title: this.currentQuery || '产业链分析',
          type: 'industry',
          articleCount: uniqueArticles.length,
          analysisCount: 0
        },
        articles: uniqueArticles.map(article => {
          // 确保每篇文章都有所有必要的字段
          return {
            title: article.title || '未知标题',
            url: article.url || '#',
            summary: article.summary || '',
            // 添加默认值确保格式一致性
            source: article.source || '行业报告',
            date: article.date || new Date().toLocaleDateString(),
            type: article.type || 'industry'
          };
        })
      };
      
      // 发送更新事件给侧边栏
      // console.log('发送侧边栏更新事件，文章数量:', uniqueArticles.length);
      this.$root.$emit('update-sidebar', this.localRelatedContent);
      
      // 清空文章收集数组和URL集合，确保下次请求时重新开始
      this.accumulatedArticles = [];
      this.articleUrlSet.clear();
      
      // console.log('侧边栏更新完成，累积文章已重置');
    },
    
    // 辅助方法：移除重复文章
    removeDuplicates(articles) {
      if (!articles || !Array.isArray(articles)) {
        console.warn('removeDuplicates收到无效的文章数组');
        return [];
      }
      
      const uniqueArticles = [];
      const urlSet = new Set();
      const titleSet = new Set();
      
      articles.forEach(article => {
        // 如果文章对象无效，跳过
        if (!article || typeof article !== 'object') {
          console.warn('跳过无效文章对象');
          return;
        }
        
        // 获取标题和URL，提供默认值以防字段缺失
        const title = article.title || '';
        const url = article.url || '';
        
        // 如果标题或URL为空，跳过
        if (!title || !url) {
          console.warn('跳过缺少标题或URL的文章');
          return;
        }
        
        // 创建唯一键进行去重判断
        const key = `${title}|${url}`;
        
        // 如果URL或标题已存在，则跳过
        if (urlSet.has(url) || titleSet.has(title)) {
          // console.log(`跳过重复文章: ${title}`);
          return;
        }
        
        // 添加到去重集合中
        urlSet.add(url);
        titleSet.add(title);
        
        // 添加到结果数组
        uniqueArticles.push(article);
      });
      
      // console.log(`文章去重完成，结果数量: ${uniqueArticles.length}`);
      return uniqueArticles;
    },
  }
}
</script>

<style scoped>
@import './styles.css';

.file-list-popover {
  max-height: 300px;
  overflow-y: auto;
}

.no-files {
  color: #909399;
  text-align: center;
  padding: 10px;
}

.file-list {
  display: flex;
  flex-direction: column;
  gap: 8px;
}

.file-item {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 8px;
  border-radius: 4px;
  background-color: #f5f7fa;
}

.file-info {
  display: flex;
  align-items: center;
  gap: 8px;
}

.file-name {
  font-size: 14px;
  color: #606266;
  max-width: 200px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.file-actions {
  display: flex;
  align-items: center;
}

.delete-btn {
  padding: 2px 6px;
}

.delete-btn:hover {
  color: #f56c6c;
}

.file-count {
  margin-left: 4px;
  font-size: 12px;
  color: #909399;
}

.mindmap-container {
  width: 800px;
  height: 500px;
  margin: 10px 0;
  border-radius: 8px;
  overflow: hidden;
  background-color: #fff;
}

.loading-indicator {
  margin: 10px 0;  /* 修改为上下外边距 */
  width: fit-content;
  background-color: #f5f5f5;
  border-radius: 12px;
  display: flex;
  align-items: center;
  padding: 8px 16px;
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
}

.loading-dots {
  display: flex;
  gap: 4px;  /* 减小点的间距 */
}

.loading-dots span {
  width: 6px;  /* 减小点的大小 */
  height: 6px;
  background-color: #1a73e8;
  border-radius: 50%;
  animation: blink 1.4s infinite both;
  opacity: 0.7;
}

.loading-dots span:nth-child(2) {
  animation-delay: 0.2s;
}

.loading-dots span:nth-child(3) {
  animation-delay: 0.4s;
}

@keyframes blink {
  0%, 80%, 100% {
    transform: scale(0.5);
    opacity: 0.4;
  }
  40% {
    transform: scale(1);
    opacity: 1;
  }
}

.loading-text {
  margin-left: 8px;
  font-size: 13px;  /* 减小字体大小 */
  color: #333;
  font-weight: 500;
}
</style>
